package com.ruov.framework.aspectj;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.ruov.common.annotation.Download;
import com.ruov.common.config.RuoYiConfig;
import com.ruov.common.constant.Constants;
import com.ruov.common.utils.StringUtils;
import com.ruov.common.utils.file.FileUtils;

/**
 * 下载操作处理
 */
@Aspect
@Component
public class DownloadAspect {
    private static final Logger log = LoggerFactory.getLogger(DownloadAspect.class);
    
    /**
     * 环绕通知处理
     */
    @Around("@annotation(download)")
    public Object doAround(ProceedingJoinPoint joinPoint, Download download) throws Throwable {
        // 执行原始方法
        Object result = joinPoint.proceed();
        
        if (result == null) {
            log.warn("下载文件不存在");
            return null;
        }
        
        // 获取当前请求和响应对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        
        // 根据返回值类型自动处理下载
        try {
            if (result instanceof File) {
                // 文件类型
                downloadFile((File) result, download, response);
            } else if (result instanceof String) {
                String path = (String) result;
                if (path.startsWith("http://") || path.startsWith("https://")) {
                    // 网络URL类型
                    downloadNetworkUrl(path, download, response);
                } else {
                    // 系统URL类型
                    downloadSystemUrl(path, download, response);
                }
            } else {
                log.error("不支持的下载返回类型: {}", result.getClass().getName());
                return result;
            }
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }
        
        // 返回null表示已经处理了响应
        return null;
    }
    
    /**
     * 处理文件类型下载
     */
    private void downloadFile(File file, Download download, HttpServletResponse response) throws IOException {
        if (!file.exists()) {
            log.error("下载文件不存在: {}", file.getAbsolutePath());
            return;
        }
        
        String fileName = StringUtils.isNotEmpty(download.fileName()) ? download.fileName() : file.getName();
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        FileUtils.setAttachmentResponseHeader(response, fileName);
        FileUtils.writeBytes(file.getAbsolutePath(), response.getOutputStream());
        
        // 是否删除源文件
        if (download.deleteSource()) {
            FileUtils.deleteFile(file.getAbsolutePath());
        }
    }
    
    /**
     * 处理系统URL类型下载
     */
    private void downloadSystemUrl(String filePath, Download download, HttpServletResponse response) throws IOException {
        if (StringUtils.isEmpty(filePath)) {
            log.error("下载文件路径为空");
            return;
        }
        
        // 检查文件是否允许下载
        if (!FileUtils.checkAllowDownload(filePath)) {
            log.error("文件({})非法，不允许下载。", filePath);
            return;
        }
        
        // 如果是资源路径，处理真实路径
        if (filePath.startsWith(Constants.RESOURCE_PREFIX)) {
            String localPath = RuoYiConfig.getProfile();
            filePath = localPath + StringUtils.substringAfter(filePath, Constants.RESOURCE_PREFIX);
        }
        
        // 下载名称
        String fileName = StringUtils.isNotEmpty(download.fileName()) ? download.fileName() : 
                          StringUtils.substringAfterLast(filePath, "/");
        
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        FileUtils.setAttachmentResponseHeader(response, fileName);
        FileUtils.writeBytes(filePath, response.getOutputStream());
        
        // 是否删除源文件
        if (download.deleteSource()) {
            FileUtils.deleteFile(filePath);
        }
    }
    
    /**
     * 处理网络URL类型下载
     */
    private void downloadNetworkUrl(String urlPath, Download download, HttpServletResponse response) throws IOException {
        if (StringUtils.isEmpty(urlPath)) {
            log.error("下载URL为空");
            return;
        }
        
        InputStream inputStream = null;
        try {
            URL url = new URL(urlPath);
            URLConnection connection = url.openConnection();
            connection.setConnectTimeout(30 * 1000);
            connection.setReadTimeout(60 * 1000);
            connection.setDoInput(true);
            inputStream = connection.getInputStream();
            
            // 下载名称
            String fileName = StringUtils.isNotEmpty(download.fileName()) ? download.fileName() : 
                             StringUtils.substringAfterLast(urlPath, "/");
            
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, fileName);
            
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                response.getOutputStream().write(buffer, 0, len);
            }
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("关闭输入流失败", e);
                }
            }
        }
    }
}
